using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Application.Services;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Shared.Enums;

namespace UniversalAdmin.Application.Services;

public class RagService : IRagService
{
    private readonly IDocumentService _documentService;
    private readonly IChatHistoryService _chatHistoryService;
    private readonly IDocumentPermissionService _documentPermissionService;

    public RagService(
        IDocumentService documentService,
        IChatHistoryService chatHistoryService,
        IDocumentPermissionService documentPermissionService)
    {
        _documentService = documentService;
        _chatHistoryService = chatHistoryService;
        _documentPermissionService = documentPermissionService;
    }

    public async Task<List<RelatedDocumentDto>> GetRelatedDocumentsAsync(Guid userId, string query, int topK = 5)
    {
        // 获取用户可访问的文档ID
        var accessibleDocumentIds = await _documentPermissionService.GetAccessibleDocumentIdsAsync(
            userId, PermissionType.Read);

        if (!accessibleDocumentIds.Any())
        {
            return new List<RelatedDocumentDto>();
        }

        // 获取文档内容
        var documents = new List<DocumentDto>();
        foreach (var documentId in accessibleDocumentIds)
        {
            var doc = await _documentService.GetDocumentByIdAsync(documentId);
            if (doc != null)
            {
                documents.Add(doc);
            }
        }

        // 简单的相关性匹配 (实际应用中应使用更复杂的算法或向量数据库)
        var relatedDocuments = documents
            .Select(doc => new
            {
                Document = doc,
                Score = CalculateRelevanceScore(doc, query)
            })
            .Where(x => x.Score > 0)
            .OrderByDescending(x => x.Score)
            .Take(topK)
            .Select(x => new RelatedDocumentDto
            {
                DocumentId = x.Document.Id,
                Title = x.Document.Title,
                Content = x.Document.Content.Length > 300 ? x.Document.Content[..300] + "..." : x.Document.Content,
                Score = x.Score
            })
            .ToList();

        return relatedDocuments;
    }

    public async Task<string> GenerateAnswerAsync(Guid userId, string query, string sessionId, List<RelatedDocumentDto> relatedDocuments)
    {
        // 获取会话上下文
        var context = await GetSessionContextAsync(sessionId);

        // 构建提示
        var promptBuilder = new StringBuilder();
        promptBuilder.AppendLine("你是一个智能助手，根据提供的文档内容和对话上下文回答用户问题。");
        promptBuilder.AppendLine("以下是对话上下文：");
        promptBuilder.AppendLine(context);
        promptBuilder.AppendLine("以下是相关文档内容：");

        foreach (var doc in relatedDocuments)
        {
            promptBuilder.AppendLine($"文档标题：{doc.Title}");
            promptBuilder.AppendLine($"文档内容：{doc.Content}");
            promptBuilder.AppendLine();
        }

        promptBuilder.AppendLine("用户问题：");
        promptBuilder.AppendLine(query);
        promptBuilder.AppendLine("请基于以上信息回答用户问题，不要添加额外信息。");

        // 在实际应用中，这里应该调用LLM服务生成回答
        // 为了演示，我们简单返回一个模拟的回答
        return "这是基于文档内容生成的回答。在实际应用中，这里会调用LLM服务来生成真实的回答。";
    }

    public async Task<ChatHistoryDto> ProcessQueryAsync(Guid userId, string query, string sessionId)
    {
        // 获取相关文档
        var relatedDocuments = await GetRelatedDocumentsAsync(userId, query);

        // 生成回答
        var answer = await GenerateAnswerAsync(userId, query, sessionId, relatedDocuments);

        // 保存对话历史
        var chatHistoryDto = await _chatHistoryService.CreateChatHistoryAsync(new CreateChatHistoryDto
        {
            UserId = userId,
            SessionId = sessionId,
            Query = query,
            Answer = answer,
            RelatedDocuments = relatedDocuments
        });

        return chatHistoryDto;
    }

    public async Task<string> GetSessionContextAsync(string sessionId, int maxTokens = 1000)
    {
        var chatHistories = await _chatHistoryService.GetChatHistoriesBySessionIdAsync(sessionId);
        if (chatHistories == null || !chatHistories.Any())
        {
            return string.Empty;
        }

        // 构建会话上下文
        var contextBuilder = new StringBuilder();
        foreach (var history in chatHistories.OrderBy(h => h.CreatedAt))
        {
            contextBuilder.AppendLine($"用户: {history.Query}");
            contextBuilder.AppendLine($"助手: {history.Answer}");
            contextBuilder.AppendLine();
        }

        // 简单的token限制 (实际应用中应使用更准确的token计数方法)
        var context = contextBuilder.ToString();
        if (context.Length > maxTokens)
        {
            context = context.Substring(context.Length - maxTokens);
        }

        return context;
    }

    // 简单的相关性评分计算
    private double CalculateRelevanceScore(DocumentDto document, string query)
    {
        // 实际应用中应使用更复杂的算法或向量数据库
        var score = 0.0;
        var queryWords = query.ToLower().Split(' ', StringSplitOptions.RemoveEmptyEntries);
        var docContent = document.Content.ToLower();
        var docTitle = document.Title.ToLower();

        foreach (var word in queryWords)
        {
            if (docTitle.Contains(word))
            {
                score += 2.0; // 标题匹配权重更高
            }
            if (docContent.Contains(word))
            {
                score += 1.0;
            }
        }

        return score;
    }
}